package com.alisls.demo.springcloud.service.user.web.login;

import com.alisls.demo.springcloud.common.model.dto.DataResult;
import com.alisls.demo.springcloud.common.model.dto.Result;
import com.alisls.demo.springcloud.service.user.client.oauth.ClientDetailFeignClient;
import com.alisls.demo.springcloud.service.user.client.oauth.TokenFeignClient;
import com.alisls.demo.springcloud.service.user.constant.AuthorizedGrantTypeEnum;
import com.alisls.demo.springcloud.service.user.dto.client.OAuthClientDetailDTO;
import com.alisls.demo.springcloud.service.user.dto.client.OAuthClientDetailPwdDTO;
import com.alisls.demo.springcloud.service.user.dto.login.AccountDTO;
import com.alisls.demo.springcloud.service.user.dto.login.AccountResult;
import com.alisls.demo.springcloud.service.user.dto.login.TokenQuery;
import lombok.extern.log4j.Log4j2;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.util.Base64;

/**
 * 账号登录
 *
 * @author Ke Wang
 * @date 2020/11/11
 */
@RestController
@RequestMapping("/login")
@Log4j2
public class LoginController {

    private final String AUTHORIZATION_PREFIX = "Basic ";

    @Resource
    private ClientDetailFeignClient clientDetailFeignClient;

    @Resource
    private TokenFeignClient tokenFeignClient;

    /**
     * 账号登录
     * @param authorization
     *   从header中获取属性Authorization的值，
     *   Authorization值是Basic + 空格 + <客户端ID>:<客户端密码>组成的字符串进行Base64加密后的字符串
     * @param tokenQuery
     * @return
     */
    @PostMapping("/account")
    public Result account(@RequestHeader(value = "Authorization", required = false) String authorization,
                          @RequestBody AccountDTO accountDTO) throws UnsupportedEncodingException {
        if (StringUtils.isEmpty(authorization)) {
            //return DataResult.ofFail("请求头中缺少authorization信息");
            authorization = "Basic d3d3LmFsaXNscy5jb206MTIzNDU2"; // TODO 开发调试临时赋值
        }

        if (!authorization.startsWith(AUTHORIZATION_PREFIX)) {
            return DataResult.ofFail("请求头中缺少authorization格式正确！");
        }
        log.info("从Header中获取Authorization属性{}", authorization);

        // 获取客户端信息
        OAuthClientDetailPwdDTO oAuthClientDetailPwdDTO = getClientInfo(authorization);
        // 对客户端有效性进行校验
        DataResult<OAuthClientDetailDTO> result = clientDetailFeignClient.getByClientId(oAuthClientDetailPwdDTO.getClientId());
        OAuthClientDetailDTO oAuthClientDetailDTO = result.getData();
        if (oAuthClientDetailDTO == null ||
                oAuthClientDetailDTO.getClientId() == null ||
                StringUtils.isEmpty(oAuthClientDetailDTO.getClientId())) {
            return DataResult.ofFail("非法的OAuth客户端！");
        }

        // 客户端所有的授权模式
        String authorizedGrantTypes = oAuthClientDetailDTO.getAuthorizedGrantTypes();

        // 判断客户端的授权模式是否有密码模式
        isLegalGrantType(authorizedGrantTypes, AuthorizedGrantTypeEnum.PASSWORD.getGrantType());

        TokenQuery tokenQuery = new TokenQuery();
        tokenQuery.setGrantType(AuthorizedGrantTypeEnum.PASSWORD.getGrantType());
        tokenQuery.setUsername(accountDTO.getUserName());
        tokenQuery.setPassword(accountDTO.getPassword());

        // 密码模式获取Token
        String token = tokenFeignClient.token(authorization,
                tokenQuery.getGrantType(),
                tokenQuery.getUsername(),
                tokenQuery.getPassword());

        return AccountResult.ok(token);
    }

    private void isLegalGrantType(String authorizedGrantTypes, String grantType) {
        if (authorizedGrantTypes == null) {
            throw new RuntimeException("非法的授权模式");
        }

        boolean isLegal = false;
        String[] grantTypeArr = authorizedGrantTypes.split(",");
        for (String existGrantType: grantTypeArr) {
            if (StringUtils.isEmpty(existGrantType)) {
                continue;
            }

            if (existGrantType.equalsIgnoreCase(grantType)) {
                isLegal = true;
                break;
            }
        }

        if (!isLegal) {
            throw new RuntimeException("非法的授权模式");
        }
    }

    private OAuthClientDetailPwdDTO getClientInfo(String authorization) throws UnsupportedEncodingException {
        authorization = authorization.replace(AUTHORIZATION_PREFIX, "");

        Base64.Decoder decoder = Base64.getDecoder();
        String clientInfo = new String(decoder.decode(authorization.getBytes()), "utf-8");
        String[] clientInfoArr = clientInfo.split(":");
        OAuthClientDetailPwdDTO authClientDetailPwdDTO = new OAuthClientDetailPwdDTO();
        authClientDetailPwdDTO.setClientId(clientInfoArr[0]);
        // 客户端的原始密码
        authClientDetailPwdDTO.setClientSecret(clientInfoArr[1]);
        return authClientDetailPwdDTO;
    }

}
